using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Matrix.Xmpp;
using Matrix.Xmpp.Client;

namespace Chat.Backend.Services.Chat
{
    /// <summary>
    /// XMPP服务 - 负责处理与XMPP服务器的连接和通信
    /// 转换自XmppHelpService.java
    /// </summary>
    public class XmppService : BackgroundService
    {
        private readonly ILogger<XmppService> _logger;
        private readonly IChatConfigService _configService;
        private readonly IEventBus _eventBus;
        private XmppClient _xmppClient;
        private static readonly SemaphoreSlim _connectionLock = new SemaphoreSlim(1, 1);
        
        // 当前连接的服务器时间，用于错误报告
        private string _connectionTimestamp;

        /// <summary>
        /// 构造函数
        /// </summary>
        public XmppService(
            ILogger<XmppService> logger,
            IChatConfigService configService,
            IEventBus eventBus)
        {
            _logger = logger;
            _configService = configService;
            _eventBus = eventBus;
        }

        /// <summary>
        /// 服务启动时执行的方法
        /// </summary>
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("XMPP服务启动");
            
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    // 检查连接状态，尝试重连
                    if (_xmppClient == null || !_xmppClient.Connected)
                    {
                        await ConnectToXmppServerAsync();
                    }
                    
                    await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "XMPP服务执行过程中发生错误");
                    await ReportErrorAsync(ex);
                }
            }
        }

        /// <summary>
        /// 连接到XMPP服务器
        /// </summary>
        public async Task ConnectToXmppServerAsync()
        {
            // 使用锁确保同一时间只有一个线程尝试连接
            await _connectionLock.WaitAsync();
            
            try
            {
                if (_xmppClient != null && _xmppClient.Connected)
                {
                    _logger.LogInformation("已经连接到XMPP服务器");
                    return;
                }

                // 获取XMPP配置
                var config = await _configService.GetXmppConfigAsync();
                
                // 创建XMPP客户端
                _xmppClient = new XmppClient
                {
                    Username = config.Username,
                    Password = config.Password,
                    XmppDomain = config.Domain,
                    HostnameResolver = (_, _) => config.Hostname,
                    Port = config.Port,
                    Resource = "chat_backend"
                };

                // 注册事件处理器
                _xmppClient.StateChanged += OnXmppStateChanged;
                _xmppClient.Message += OnXmppMessage;
                
                // 连接到服务器
                _connectionTimestamp = DateTime.UtcNow.ToString("o");
                await _xmppClient.ConnectAsync();
                
                _logger.LogInformation($"已连接到XMPP服务器: {config.Hostname}");
                
                // 通知连接成功
                await _eventBus.PublishAsync(new XmppConnectedEvent
                {
                    Connected = true,
                    Timestamp = _connectionTimestamp
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "连接XMPP服务器失败");
                await ReportErrorAsync(ex);
                
                // 通知连接失败
                await _eventBus.PublishAsync(new XmppConnectedEvent
                {
                    Connected = false,
                    Error = ex.Message
                });
                
                // 释放客户端资源
                _xmppClient?.Dispose();
                _xmppClient = null;
            }
            finally
            {
                _connectionLock.Release();
            }
        }

        /// <summary>
        /// 使用指定的账号登录XMPP服务器
        /// </summary>
        public async Task LoginAsync(string username, string password)
        {
            await _connectionLock.WaitAsync();
            
            try
            {
                if (_xmppClient == null || !_xmppClient.Connected)
                {
                    await ConnectToXmppServerAsync();
                }
                
                // 检查当前登录状态
                if (_xmppClient.Authenticated && _xmppClient.Username == username)
                {
                    _logger.LogInformation($"用户 {username} 已登录，无需重新登录");
                    return;
                }
                
                // 设置新的凭据
                _xmppClient.Username = username;
                _xmppClient.Password = password;
                
                // 登录
                await _xmppClient.AuthenticateAsync();
                
                _logger.LogInformation($"用户 {username} 登录成功");
                
                // 通知登录成功
                await _eventBus.PublishAsync(new XmppAuthenticatedEvent
                {
                    Username = username,
                    Authenticated = true
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"用户 {username} 登录失败");
                await ReportErrorAsync(ex);
                
                // 通知登录失败
                await _eventBus.PublishAsync(new XmppAuthenticatedEvent
                {
                    Username = username,
                    Authenticated = false,
                    Error = ex.Message
                });
                
                // 重新连接
                _xmppClient?.Dispose();
                _xmppClient = null;
            }
            finally
            {
                _connectionLock.Release();
            }
        }

        /// <summary>
        /// 加入群聊
        /// </summary>
        public async Task JoinGroupAsync(string roomJid, string nickname)
        {
            try
            {
                if (_xmppClient == null || !_xmppClient.Connected || !_xmppClient.Authenticated)
                {
                    throw new InvalidOperationException("需要先连接并登录到XMPP服务器");
                }
                
                // 创建MUC (Multi-User Chat) 请求
                var muc = new Matrix.Xmpp.Muc.Muc();
                await _xmppClient.SendAsync(muc.GetPresence(roomJid, nickname));
                
                _logger.LogInformation($"已加入群聊: {roomJid}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"加入群聊失败: {roomJid}");
                await ReportErrorAsync(ex);
                throw;
            }
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        public async Task SendMessageAsync(string to, string body, MessageType type = MessageType.Chat)
        {
            try
            {
                if (_xmppClient == null || !_xmppClient.Connected || !_xmppClient.Authenticated)
                {
                    throw new InvalidOperationException("需要先连接并登录到XMPP服务器");
                }
                
                // 创建消息
                var message = new Matrix.Xmpp.Client.Message
                {
                    To = to,
                    Type = type.ToString().ToLowerInvariant(),
                    Body = body
                };
                
                // 发送消息
                await _xmppClient.SendAsync(message);
                
                _logger.LogInformation($"已发送消息到: {to}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"发送消息失败: {to}");
                await ReportErrorAsync(ex);
                throw;
            }
        }

        /// <summary>
        /// XMPP状态改变事件处理
        /// </summary>
        private void OnXmppStateChanged(object sender, Matrix.StateChangedEventArgs args)
        {
            _logger.LogInformation($"XMPP状态改变: {args.State}");
            
            // 根据状态变化采取相应的行动
            switch (args.State)
            {
                case Matrix.XmppConnectionState.Disconnected:
                    _eventBus.PublishAsync(new XmppStateChangedEvent
                    {
                        State = "Disconnected"
                    }).Wait();
                    break;
                    
                case Matrix.XmppConnectionState.Connected:
                    _eventBus.PublishAsync(new XmppStateChangedEvent
                    {
                        State = "Connected"
                    }).Wait();
                    break;
                    
                case Matrix.XmppConnectionState.Authenticated:
                    _eventBus.PublishAsync(new XmppStateChangedEvent
                    {
                        State = "Authenticated"
                    }).Wait();
                    break;
            }
        }

        /// <summary>
        /// 接收消息事件处理
        /// </summary>
        private void OnXmppMessage(object sender, Matrix.Xmpp.Client.MessageEventArgs args)
        {
            var message = args.Message;
            _logger.LogInformation($"收到消息，来自: {message.From}, 内容: {message.Body}");
            
            // 转发消息到事件总线
            _eventBus.PublishAsync(new XmppMessageReceivedEvent
            {
                From = message.From.ToString(),
                To = message.To.ToString(),
                Body = message.Body,
                Type = message.Type,
                Id = message.Id
            }).Wait();
            
            // 发送消息回执
            if (!string.IsNullOrEmpty(message.Id))
            {
                var receipt = new Matrix.Xmpp.Client.Message
                {
                    To = message.From.ToString(),
                    Type = "chat",
                    Id = Guid.NewGuid().ToString()
                };
                
                var receiptElement = new Matrix.Xmpp.Base.Element("received", "urn:xmpp:receipts");
                receiptElement.SetAttribute("id", message.Id);
                receipt.Add(receiptElement);
                
                _xmppClient.SendAsync(receipt).Wait();
            }
        }

        /// <summary>
        /// 向服务器报告错误
        /// </summary>
        private async Task ReportErrorAsync(Exception error)
        {
            try
            {
                var errorReport = new ErrorReport
                {
                    AppName = "Chat Backend",
                    Version = GetType().Assembly.GetName().Version.ToString(),
                    ErrorMessage = error.Message,
                    StackTrace = error.StackTrace,
                    ConnectionInfo = $"主机: {_configService.GetXmppConfigAsync().Result.Hostname}, 端口: {_configService.GetXmppConfigAsync().Result.Port}",
                    SystemInfo = Environment.OSVersion.ToString(),
                    NetworkStatus = NetworkStatus.GetNetworkStatus(),
                    Timestamp = DateTime.UtcNow,
                    ConnectionTimestamp = _connectionTimestamp
                };
                
                await _configService.ReportErrorAsync(errorReport);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "报告错误失败");
            }
        }

        /// <summary>
        /// 当服务停止时销毁资源
        /// </summary>
        public override void Dispose()
        {
            _xmppClient?.Dispose();
            base.Dispose();
        }
    }

    /// <summary>
    /// 消息类型枚举
    /// </summary>
    public enum MessageType
    {
        Chat,
        GroupChat,
        Error,
        Headline,
        Normal
    }
}